//ICS 314 - sundail project
//Yosetime Group
//Spring 2013
import java.util.Calendar;
import java.lang.Math;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class Calculator {
public static double longitude;
public static double latitude;
public static String time;
public static double clockTime;
public static boolean dayLightSavings;
public static String timeString;

/**
* Calculates the angle to return to the gnome.
*
* Author Kingtak Justin Wong
*
* 
*/
public static double calculate() throws NumberFormatException{

    //get the required information
	  longitude = mainUI.getLongitude();
	  //System.out.println(longitude);
	  latitude = mainUI.getLatitude();
	  //System.out.println(latitude);
	  if (longitude > 180 || longitude < -180 || latitude > 180 || latitude < -180) {
		  throw new NumberFormatException("Longitude or Latitude out of bounds");
	  }
	  String monthString, dayString,yearString;
	  Calendar calendar;
	  final int YEAR_LENGTH = 365;
	  double E;
	  int year,hour, month, day, currentMeridian = -150, minute, B, dayOfYear=1;
	  int monthLength=0;
	  double timeDisplac; 
    double equaOfTime, timeAngle;
    String hourString,minuteString;
	  float hourArc,minuteArc;
	  
	  //set the meridians to use
     final int NEWFOUNDLAND = 52;
     final int ATLANTIC = 60;
     final int EASTERN = 75;
     final int CENTRAL = 90;
     final int MOUNTIAN = 105;
     final int PACIFIC = 120;
     final int YUKON = 135;
     final int ALASKA_HAWAII = 150;
     final int BERING = 165;
	   final int POLYNESIA = 180;
     final int AZORES = 15;
	   final int WEST_AFRICA = 0;
	   final int WEST_ATLANTIC = 30;
     
     //get the month
	   time = mainUI.getDate();
     monthString = time.substring(2,4);
     
     //get the day
     dayString = time.substring(0,2);
     //get the year
     yearString = time.substring(4,8);

	  //trim the first number of month if it is not 1
	  if(monthString.charAt(0)=='0'){
	    monthString = monthString.substring(1,2);
	  }
	  //change it to a number
	  month=Integer.parseInt(monthString);
     
	  //do the same thing for the day
	  if(dayString.charAt(0)=='0'){
	    dayString = monthString.substring(1,2);
	  }
	  
	  //change it to a number
	  day=Integer.parseInt(dayString);

	  //change the year into a number
	  year = Integer.parseInt(yearString);

	  for(int i = 1; i <= month; i++){
	    if(i == 3){
		   if((year%4)==0)
			  monthLength += 29;
			else
			  monthLength += 28;
		 }
		 if(i==5||i==7||i==10||i==12){
		   monthLength += 30;
		 }
		 if(i==2||i==4||i==6||i==8||i==9||i==11){
			monthLength += 31;
       }
	  }
	  

	  dayOfYear = monthLength + day;
		 //call a new calendar instance
       calendar = Calendar.getInstance();
	    DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");	
	  	 timeString = dateFormat.format(calendar.getTime());

     //if(!custom){
	    

	    hourString = timeString.substring(0,2);
	   
		 if(hourString.charAt(0)=='0'){
	      hourString = hourString.substring(1,2);
	    }
	    
		 hour=Integer.parseInt(hourString);
	    
		 minuteString = timeString.substring(3,5);
	  
	    if(minuteString.charAt(0)=='0'){
	      minuteString = minuteString.substring(1,2);
	    }

	    minute = Integer.parseInt(minuteString);

	  //}
	  //else{ 
	  //}
	  
	  //first find out which meridian to use
	  if(isBetween(Math.abs(longitude), 0, 15)){currentMeridian = WEST_AFRICA;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 15, 29)){currentMeridian = AZORES;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 30, 44)){currentMeridian = WEST_ATLANTIC;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 45, 59)){currentMeridian = NEWFOUNDLAND;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 60, 74)){currentMeridian = ATLANTIC;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 75, 89)){currentMeridian = EASTERN;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 90, 104)){currentMeridian = CENTRAL;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 105, 119)){currentMeridian = MOUNTIAN;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 120, 134)){currentMeridian = PACIFIC;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 135, 149)){currentMeridian = YUKON;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 150, 154)){currentMeridian = ALASKA_HAWAII;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 155, 164)){currentMeridian = BERING;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  if(isBetween(Math.abs(longitude), 165, 180)){currentMeridian = POLYNESIA;if(longitude<=0){currentMeridian =currentMeridian*-1;}}
	  //correct for the first refinement below
     timeDisplac = Math.abs(longitude) - Math.abs(currentMeridian);
	  timeDisplac = Math.abs(timeDisplac)*4;
	  if(currentMeridian <= 0){
	    clockTime = clockTime - timeDisplac;
     }
	  else{
	    clockTime = clockTime + timeDisplac;
	  }
	  //System.out.println(clockTime);
	  // E = 9.87*sin(2*B)-7.53*cos(B)-1.5*sin(B)
     //solve for B in EOT equation
     //B relies on the specific day of the year
     B = 360*dayOfYear/YEAR_LENGTH;
     //can solve for the general solution now
     //remember that Math class takes radians 
     E = 9.87*Math.sin(Math.toRadians(2*B))-7.53*Math.cos(Math.toRadians(B))-1.5*Math.sin(Math.toRadians(B));
  	  clockTime = clockTime + E;
	  
	  if(dayLightSavings) {
	    clockTime++;
	  }
	  hourArc = hour*15;
     minuteArc = minute*15;  
	  timeAngle=hourArc+((minuteArc/60))+clockTime;

	  //solve the Equation of Time equation
	  equaOfTime = Math.atan(Math.tan(Math.toRadians(timeAngle))*Math.sin(Math.toRadians(Math.abs(latitude))));
	  equaOfTime = Math.toDegrees(equaOfTime);
//	  System.out.println(equaOfTime);
	  return equaOfTime;
  //When calculation is done, should call Painter.draw to create the image
  }
  
  public static boolean isBetween(double x, int lower, int upper) {
    return lower <= x && x <= upper;
  }
}